#include "main.h"
#include "ethernetif.h"

/* Network interface name */
#define IFNAME0 's'
#define IFNAME1 't'

uint8_t MACAddr[6];                         //MAC address

struct ethernetif
{
    struct eth_addr *ethaddr;
    /* Add whatever per-interface state that is needed here. */
};

u32_t sys_now(void)
{
    return LocalTime;
}

static void low_level_init(struct netif *netif)
{
    WCHNET_GetMacAddr(MACAddr);                                 //get the chip MAC address

    printf("MACAddr: ");
    for (int i = 0; i < 6; i++)
    {
        printf("%02X", MACAddr[i]);
        if( i < 5)
        {
            printf("-");
        }
        else
        {
            printf("\r\n");
        }
    }
    
    ETH_Init(MACAddr);

    /* Set netif link flag */
    netif->flags |= NETIF_FLAG_LINK_UP;

#if LWIP_ARP || LWIP_ETHERNET

    /* set MAC hardware address length */
    netif->hwaddr_len = ETH_HWADDR_LEN;

    /* set MAC hardware address */
    netif->hwaddr[0] =  MACAddr[0];
    netif->hwaddr[1] =  MACAddr[1];
    netif->hwaddr[2] =  MACAddr[2];
    netif->hwaddr[3] =  MACAddr[3];
    netif->hwaddr[4] =  MACAddr[4];
    netif->hwaddr[5] =  MACAddr[5];

    /* maximum transfer unit */
    netif->mtu = NETIF_MTU;

#if LWIP_ARP
    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
#else
    netif->flags |= NETIF_FLAG_BROADCAST;
#endif /* LWIP_ARP */

#endif /* LWIP_ARP || LWIP_ETHERNET */

    ETH_Start();
}

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
    // printf("write %d\r\n", p->tot_len);
    
    uint8_t *buffer = malloc(p->tot_len);
    struct pbuf *q = p;
    uint32_t offset = 0;

    while (q != NULL)
    {
        memcpy(buffer + offset, q->payload, q->len);
        offset += q->len;
        q = q->next;
    }
    
    MACRAW_Tx(buffer, p->tot_len);

    free(buffer);

    return ERR_OK;
}

#if !LWIP_ARP

static err_t low_level_output_arp_off(struct netif *netif, struct pbuf *q, con
ip4_addr_t *ipaddr)
{
    err_t errval;
    errval = ERR_OK;

    return errval;

}
#endif /* LWIP_ARP */

err_t ethernetif_init(struct netif *netif)
{
    struct ethernetif *ethernetif;

//  LWIP_ASSERT("netif != NULL", (netif != NULL));

    ethernetif = mem_malloc(sizeof(struct ethernetif));

    if (ethernetif == NULL)
    {
        PRINT_ERR("ethernetif_init: out of memory\n");
        return ERR_MEM;
    }

    LWIP_ASSERT("netif != NULL", (netif != NULL));
//
#if LWIP_NETIF_HOSTNAME
    /* Initialize interface hostname */
    netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
    netif->state = ethernetif;
    netif->name[0] = IFNAME0;
    netif->name[1] = IFNAME1;

#if LWIP_IPV4
#if LWIP_ARP || LWIP_ETHERNET
#if LWIP_ARP
    netif->output = etharp_output;
#else
    netif->output = low_level_output_arp_off;
#endif /* LWIP_ARP */
#endif /* LWIP_ARP || LWIP_ETHERNET */
#endif /* LWIP_IPV4 */

#if LWIP_IPV6
    netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */

    netif->linkoutput = low_level_output;

    /* initialize the hardware */
    low_level_init(netif);
    ethernetif->ethaddr = (struct eth_addr *) &(netif->hwaddr[0]);

    return ERR_OK;
}
